//
//  VIZApplicationDelegateProxy.m
//  VIZModuleManager
//  代理类
//  Created by 位立志 on 2018/2/8.
//  Copyright © 2018 . All rights reserved.
//

@import ObjectiveC.runtime;
@import UIKit;

#import "VIZModule.h"
#import "VIZModuleManager.h"
#import "VIZApplicationDelegateProxy.h"

@implementation VIZApplicationDelegateProxy

- (Protocol *)targetProtocol {
    return @protocol(UIApplicationDelegate);
}


/**
 判定某方法是否在UIApplicationDelegate代理方法中
 */
- (BOOL)isTargetProtocolMethod:(SEL)selector {
    unsigned int outCount = 0;
    struct objc_method_description *methodDescriptions = protocol_copyMethodDescriptionList([self targetProtocol], NO, YES, &outCount);
    for (int idx = 0; idx < outCount; idx++) {
        SEL methodSel = methodDescriptions[idx].name;
        if (selector == methodSel) {
            return YES;
        }
    }

    free(methodDescriptions);
    
    return NO;
}

    // Appdelegate方法回调之前都会调用该方法，用来判断是否能够执行代理方法。
    - (BOOL)respondsToSelector:(SEL)aSelector {
        if ([self.realDelegate respondsToSelector:aSelector]) {
            return YES;
        }
        // 判断各个子业务模块是否有实现该方法
        for (VIZModule *module in [VIZModuleManager.sharedInstance allModules]) {
            if ([self isTargetProtocolMethod:aSelector] && [module respondsToSelector:aSelector]) {
                return YES;
            }
        }

        return [super respondsToSelector:aSelector];
    }

    //1、消息转发第一步。过滤UIApplicationDelegate代理方法，在本类中执行。其他appdelegate可以执行的方法则去appdelegate中执行
    //对于Appdelegate中的方法：如果不是UIApplicationDelegate的代理方法并且在Appdelegate中可以实现。则去appdelegate中执行，否则在本类中执行
    //PS:不在此处就去处理消息转发，是因为在此处只能转发到一处，无法实现需求，故在下面进行转发处理
    - (id)forwardingTargetForSelector:(SEL)aSelector {
        if (![self isTargetProtocolMethod:aSelector] && [self.realDelegate respondsToSelector:aSelector]) {
                return self.realDelegate;
        }
        return self;
    }

    //2、消息转发第二步（均是UIApplicationDelegate的方法）。 提供方法签名
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {

        struct objc_method_description methodDescription = protocol_getMethodDescription([self targetProtocol], aSelector, NO, YES);

        if (methodDescription.name == NULL && methodDescription.types == NULL) {
            return [[self class] instanceMethodSignatureForSelector:@selector(doNothing)];
        }

        return [NSMethodSignature signatureWithObjCTypes:methodDescription.types];;
    }

    //3、消息转发第三步 手动处理消息执行对象
    // 将各个UIApplicationDelegate的方法下发到realDelegate以及各个组件的module，并执行
    - (void)forwardInvocation:(NSInvocation *)anInvocation {
        // 主工程中如果有实现，先执行主工程中的生命周期方法
        if ([self.realDelegate respondsToSelector:anInvocation.selector]) {
            [anInvocation invokeWithTarget:self.realDelegate];
        }

        // 再执行子业务模块中的生命周期方法
        for (VIZModule *module in [VIZModuleManager.sharedInstance allModules] ) {
            if ([module respondsToSelector:anInvocation.selector]) {
                [anInvocation invokeWithTarget:module];
            }
        }
    }

- (void)doNothing {}

@end
